package com.furtherstar.auth.service.impl;

import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.furtherstar.auth.controller.dto.UserCreator;
import com.furtherstar.auth.controller.dto.UserQuery;
import com.furtherstar.auth.dao.enums.Disabled;
import com.furtherstar.auth.dao.mapper.AuthUserMapper;
import com.furtherstar.auth.dao.mapper.CorpWorkDeptMapper;
import com.furtherstar.auth.dao.mapper.CorpWorkMapper;
import com.furtherstar.auth.dao.mapper.UserRoleMapper;
import com.furtherstar.auth.dao.model.AuthUser;
import com.furtherstar.auth.dao.model.AuthUserExample;
import com.furtherstar.auth.dao.model.AuthUserExample.Criteria;
import com.furtherstar.auth.dao.model.CorpWork;
import com.furtherstar.auth.dao.model.CorpWorkDept;
import com.furtherstar.auth.dao.model.CorpWorkDeptExample;
import com.furtherstar.auth.dao.model.CorpWorkExample;
import com.furtherstar.auth.dao.model.UserRole;
import com.furtherstar.auth.dao.model.UserRoleExample;
import com.furtherstar.auth.dao.model.UserSecret;
import com.furtherstar.auth.service.AuthUserService;
import com.furtherstar.auth.service.UserSecretService;
import com.furtherstar.auth.util.PasswordUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageSerializable;
import com.yummy.convention.encrypt.Encrypt;
import com.yummy.convention.exception.AssertUtil;
import com.yummy.convention.lang.IDGenerator;
import com.yummy.security.User;
import com.yummy.web.context.RequestContext;
import com.yummy.web.security.bean.SimpleUser;

@Service
public class AuthUserServiceImpl implements AuthUserService{
	
	@Autowired
	private AuthUserMapper authUserMapper;
	@Autowired
	private CorpWorkMapper corpWorkMapper;
	@Autowired
	private CorpWorkDeptMapper corpWorkDeptMapper;
	@Autowired
	private UserRoleMapper userRoleMapper;
	@Autowired
	private UserSecretService userSecretService;

	@Override
	public AuthUser getByUsername(String username) {
		AuthUserExample example = new AuthUserExample();
		example.createCriteria().andUsernameEqualTo(username).andDisabledNotEqualTo(Disabled.deleted.ordinal());
		List<AuthUser> list = authUserMapper.selectByExample(example);
		if(CollectionUtils.isEmpty(list)) {
			return null;
		}
		return list.get(0);
	}

	@Override
	@Transactional
	public Long add(UserCreator userCreator) {
		AssertUtil.isTrue(!checkExist(userCreator.getUsername()),"已存在");
		AuthUser user = createUser(userCreator);
		authUserMapper.insert(user);
		userSecretService.createUserSecret(userCreator.getPassword(),user);
		return user.getId();
	}

	private AuthUser createUser(UserCreator userCreator) {
		AuthUser user = new AuthUser();
		user.setAvatar(userCreator.getAvatar());
		user.setEmail(userCreator.getEmail());
		user.setNickname(userCreator.getNickname());
		user.setUsername(userCreator.getUsername());
		user.setType(userCreator.getUserType());
		user.setMobile(userCreator.getMobile() == null ? null : Encrypt.encryptDES(userCreator.getMobile(), PasswordUtil.passwordSalt));
		createMark(user);
		return user;
	}

	private void createMark(AuthUser user) {
		user.setId(IDGenerator.getId());
		user.setDisabled(Disabled.normal.ordinal());
		User currentUser = RequestContext.getCurrentUser();
		user.setAddUserid((Long) currentUser.getUserid());
		user.setAddNickname(currentUser.getNickname());
		user.setLmUserid((Long) currentUser.getUserid());
		user.setLmNickname(currentUser.getNickname());
		Date now = new Date();
		user.setAddTime(now);
		user.setLmTime(now);
	}

	private boolean checkExist(String username) {
		AuthUserExample example = new AuthUserExample();
		example.createCriteria().andUsernameEqualTo(username).andDisabledNotEqualTo(Disabled.deleted.ordinal());
		return authUserMapper.countByExample(example) != 0;
	}

	@Override
	@Transactional
	public Long update(AuthUser authUser) {
		AuthUser old = getAuthUser(authUser.getId());
		AssertUtil.notNull(old,"找不到记录");
		authUser.setUsername(null);
		authUser.setMobile(authUser.getMobile() == null ? null : Encrypt.encryptDES(authUser.getMobile(), PasswordUtil.passwordSalt));
		optMark(authUser);
		authUserMapper.updateByPrimaryKeySelective(authUser);
		if(authUser.getNickname() != null
				&& !authUser.getNickname().equals(old.getNickname())) {
			updateRelated(authUser);
		}
		return authUser.getId();
	}

	private void updateRelated(AuthUser authUser) {
		updateWorkNickname(authUser);
		updateWorkDeptNickname(authUser);
		updateUserRoleNickname(authUser);
	}

	private void updateUserRoleNickname(AuthUser authUser) {
		UserRoleExample example = new UserRoleExample();
		example.createCriteria().andUseridEqualTo(authUser.getId());
		UserRole ur = new UserRole();
		ur.setNickname(authUser.getNickname());
		userRoleMapper.updateByExampleSelective(ur, example);
	}

	private void updateWorkDeptNickname(AuthUser authUser) {
		CorpWorkDeptExample example = new CorpWorkDeptExample();
		example.createCriteria().andUseridEqualTo(authUser.getId());
		CorpWorkDept cwd = new CorpWorkDept();
		cwd.setNickname(authUser.getNickname());
		corpWorkDeptMapper.updateByExampleSelective(cwd, example);
	}

	private void updateWorkNickname(AuthUser authUser) {
		CorpWorkExample example = new CorpWorkExample();
		example.createCriteria().andUseridEqualTo(authUser.getId());
		CorpWork cw = new CorpWork();
		cw.setNickname(authUser.getNickname());
		corpWorkMapper.updateByExampleSelective(cw, example);
	}

	private AuthUser getAuthUser(Long id) {
		return authUserMapper.selectByPrimaryKey(id);
	}

	private void optMark(AuthUser user) {
		User currentUser = RequestContext.getCurrentUser();
		user.setLmUserid((Long) currentUser.getUserid());
		user.setLmNickname(currentUser.getNickname());
		Date now = new Date();
		user.setLmTime(now);
	}

	@Override
	@Transactional
	public Boolean changePassword(UserSecret userSecret) {
		userSecretService.changePassword(userSecret.getUserid(),userSecret.getPassword());
		return true;
	}

	@Override
	public Long enable(Long userid) {
		AuthUser user = new AuthUser();
		user.setId(userid);
		user.setDisabled(Disabled.normal.ordinal());
		optMark(user);
		int row = authUserMapper.updateByPrimaryKeySelective(user);
		AssertUtil.isTrue(row == 1,"找不到记录");
		return userid;
	}

	@Override
	public Long disable(Long userid) {
		AuthUser user = new AuthUser();
		user.setId(userid);
		user.setDisabled(Disabled.disabled.ordinal());
		optMark(user);
		int row = authUserMapper.updateByPrimaryKeySelective(user);
		AssertUtil.isTrue(row == 1,"找不到记录");
		return userid;
	}

	@Override
	@Transactional
	public Boolean delete(Long userid) {
		AuthUser user = new AuthUser();
		user.setId(userid);
		user.setDisabled(Disabled.deleted.ordinal());
		optMark(user);
		int row = authUserMapper.updateByPrimaryKeySelective(user);
		AssertUtil.isTrue(row == 1,"找不到记录");
		deleteRelated(userid);
		return true;
	}

	private void deleteRelated(Long userid) {
		deleteWorkByUser(userid);
		deleteWorkDeptByUser(userid);
		deleteUserRole(userid);
	}

	private void deleteUserRole(Long userid) {
		UserRoleExample example = new UserRoleExample();
		example.createCriteria().andUseridEqualTo(userid);
		userRoleMapper.deleteByExample(example);
	}

	private void deleteWorkDeptByUser(Long userid) {
		CorpWorkDeptExample example = new CorpWorkDeptExample();
		example.createCriteria().andUseridEqualTo(userid);
		corpWorkDeptMapper.deleteByExample(example);
	}

	private void deleteWorkByUser(Long userid) {
		CorpWorkExample example = new CorpWorkExample();
		example.createCriteria().andUseridEqualTo(userid);
		corpWorkMapper.deleteByExample(example);
	}

	@Override
	public PageSerializable<AuthUser> pageQuery(UserQuery userQuery) {
		PageHelper.startPage(userQuery.getPageNum(),userQuery.getPageSize());
		AuthUserExample example = new AuthUserExample();
		Criteria criteria = example.createCriteria().andDisabledNotEqualTo(Disabled.deleted.ordinal());
		if(StringUtils.isNotBlank(userQuery.getUserKeyword())) {
			criteria.andNicknameLike("%"+userQuery.getUserKeyword()+"%");
		}
		PageSerializable<AuthUser> page = PageSerializable.of(authUserMapper.selectByExample(example));
		page.setList(page.getList().stream().map(u -> {
			if(u.getMobile() != null) {
				u.setMobile(Encrypt.decryptDES(u.getMobile(), PasswordUtil.passwordSalt));
			}
			return u;
		}).toList());
		return page;
	}

	@Override
	public PageSerializable<SimpleUser> optionsQuery(UserQuery userQuery) {
		PageHelper.startPage(userQuery.getPageNum(),userQuery.getPageSize());
		AuthUserExample example = new AuthUserExample();
		Criteria criteria = example.createCriteria().andDisabledNotEqualTo(Disabled.deleted.ordinal());
		if(StringUtils.isNotBlank(userQuery.getUserKeyword())) {
			criteria.andNicknameLike("%"+userQuery.getUserKeyword()+"%");
		}
		PageSerializable<AuthUser> authUserPage = PageSerializable.of(authUserMapper.selectByExample(example));
		if(authUserPage.getTotal() == 0) {
			return PageSerializable.of(Collections.emptyList());
		}
		List<SimpleUser> list = authUserPage.getList().stream().map(u -> {
			SimpleUser su = new SimpleUser();
			su.setAvatar(u.getAvatar());
			su.setNickname(u.getNickname());
			su.setUserid(u.getId());
			su.setUsername(u.getUsername());
			return su;
		}).toList();
		PageSerializable<SimpleUser> resultPage = PageSerializable.of(list);
		resultPage.setTotal(authUserPage.getTotal());
		return resultPage;
	}

}
